<template>
  <div class="center-container">
    <div class="container">
      <div class="handle-box">
        <el-button type="primary" id="extend-upload-chooseFile" icon="el-icon-upload2">
          选择文件
        </el-button>
        <div class="showMsg">支持上传的文件后缀：<span style="color: #f10808; font-size: 18px">{{
            options.fileType
          }}</span></div>
      </div>
      <el-table :data="fileList" style="width: 100%">
        <el-table-column prop="fileName" label="文件名称" align="center" width="180"></el-table-column>
        <el-table-column prop="fileSize" align="center" label="文件大小" width="180"></el-table-column>
        <el-table-column label="进度" align="center" width="300">
          <template slot-scope="scope">
            <div class="progress-container">
              <el-progress :text-inside="true" :stroke-width="15" :percentage="scope.row.percentage"></el-progress>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="上传速度" align="center" width="150">
          <template slot-scope="scope">
            <div>{{ scope.row.speed }}</div>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button type="text" icon="el-icon-close" class="red" @click="removeRow(scope.$index, scope.row)">移除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import $ from 'jquery'
import webUploader from 'webuploader'

export default {
  name: 'WebUpload',
  props: {
    headers: {
      type: String,
      default: ''
    },
    fileNumLimit: {
      type: Number,
      default: 100
    },
    fileSize: {
      type: Number,
      default: 100 * 1024 * 1024 * 1024
    },
    chunkSize: {
      type: Number,
      default: 1 * 1024 * 1024
    },
    uploadSuffixUrl: {
      type: String,
      default: 'http://localhost:8810'
    },
    options: {
      default: function () {
        return {
          fileType: 'doc,docx,pdf,xls,xlsx,ppt,pptx,gif,jpg,jpeg,bmp,png,rar,zip,mp4,avi',
          fileUploadUrl: '/v1/upload/zone/zoneUpload', //上传地址
          fileCheckUrl: '/v1/upload/zone/md5Check', //检测文件是否存在url
          checkChunkUrl: '/v1/upload/zone/md5Check', //检测分片url
          mergeChunksUrl: '/v1/upload/zone/merge', //合并文件请求地址 提交测试
          headers: {}
        }
      }
    },

    fileListData: {
      type: Array,
      default: function () {
        return []
      }
    }
  },
  data() {
    return {
      fileList: [], // 存储等待上传文件列表的数组
      percentage: 0, // 上传进度，初始化为0
      uploader: {}, // WebUploader实例对象
      uploadStatus: 'el-icon-upload', // 上传状态图标，默认为上传图标
      uploadStartTime: null, // 文件上传开始时间
      uploadedFiles: [] // 存储上传成功文件信息的数组
    }
  },
  mounted() {
    this.register()
    this.initUploader()
    this.initEvents()

    // 监视 fileListData 变化，并将其赋值给 fileList
    this.$watch('fileListData', (newVal) => {
      this.fileList = [...newVal];
    });

  },
  methods: {
    initUploader() {
      var fileType = this.options.fileType
      this.uploader = webUploader.create({
        // 不压缩image
        resize: false,
        // swf文件路径
        swf: '../../../assets/Uploader.swf', // swf文件路径 兼容ie的，可以不设置
        // 默认文件接收服务端。
        server: this.uploadSuffixUrl + this.options.fileUploadUrl,
        pick: {
          id: '#extend-upload-chooseFile', //指定选择文件的按钮容器
          multiple: false //开启文件多选,
        },
        accept: [
          {
            title: 'file',
            extensions: fileType,
            mimeTypes: this.buildFileType(fileType)
          }
        ],
        compressSize: 0,
        fileNumLimit: this.fileNumLimit,
        fileSizeLimit: 2 * 1024 * 1024 * 1024 * 1024,
        fileSingleSizeLimit: this.fileSize,
        chunked: true,
        threads: 10,
        chunkSize: this.chunkSize,
        prepareNextFile: false,
      })
    },

    register() {
      const that = this;
      const options = this.options;
      const uploadSuffixUrl = this.uploadSuffixUrl;
      const fileCheckUrl = uploadSuffixUrl + options.fileCheckUrl;
      const checkChunkUrl = uploadSuffixUrl + options.checkChunkUrl;
      const mergeChunksUrl = uploadSuffixUrl + options.mergeChunksUrl;

      webUploader.Uploader.register(
          {
            'before-send-file': 'beforeSendFile',
            'before-send': 'beforeSend',
            'after-send-file': 'afterSendFile'
          },
          {
            beforeSendFile: function (file) {
              const deferred = webUploader.Deferred();

              new webUploader.Uploader()
                  .md5File(file, 0, 10 * 1024 * 1024)
                  .progress(function () {
                  })
                  .then(function (val) {
                    file.fileMd5 = val

                    $.ajax({
                      type: 'POST',
                      url: fileCheckUrl,
                      data: {
                        checkType: 'FILE_EXISTS',
                        contentType: file.type,
                        zoneTotalMd5: val
                      },
                      dataType: 'json',
                      success: function (response) {
                        if (response.success) {
                          that.uploader.skipFile(file)
                          // 更新进度条
                          that.percentage = 1
                          that.$notify.success({

                            showClose: true,
                            message: `[ ${file.name} ]文件秒传`
                          })

                          that.uploadedFiles.push(response.data)
                          deferred.reject()
                        } else {
                          if (response.code === 30001) {
                            const m = response.message + '，文件后缀：' + file.ext;
                            that.uploader.skipFile(file)
                            that.setTableBtn(file.id, m)
                            that.uploadedFiles.push(response.data)
                            deferred.reject()
                          } else {
                            deferred.resolve()
                          }
                        }
                      }
                    })
                  })

              return deferred.promise()
            },
            beforeSend: function (block) {
              const deferred = webUploader.Deferred();

              new webUploader.Uploader()
                  .md5File(block.file, block.start, block.end)
                  .progress(function () {
                  })
                  .then(function (val) {
                    block.zoneMd5 = val
                    $.ajax({
                      type: 'POST',
                      url: checkChunkUrl,
                      data: {
                        checkType: 'ZONE_EXISTS',
                        zoneTotalMd5: block.file.fileMd5,
                        zoneMd5: block.zoneMd5
                      },
                      dataType: 'json',
                      success: function (response) {
                        if (response.success) {
                          deferred.reject()
                        } else {
                          deferred.resolve()
                        }
                      }
                    })
                  })
              return deferred.promise()
            },
            afterSendFile: function (file) {
              $.ajax({
                type: 'POST',
                url: mergeChunksUrl + "?totalMd5=" + file.fileMd5,
                dataType: 'JSON',
                success: function (res) {
                  if (res.success) {
                    const data = res.data.fileInfo;
                    that.uploader.skipFile(file)
                    // 更新进度条
                    that.percentage = 1
                    that.uploadedFiles.push(data)
                  }
                }

              })
            }
          }
      )
    },
    initEvents() {
      const that = this;
      const uploader = this.uploader;

      uploader.on('fileQueued', function (file) {
        // 清空现有文件列表，实现只上传单个文件
        if (!this.multiple) {
          this.fileList = []
          this.uploadedFiles = []
        }
        const fileSize = that.formatFileSize(file.size);
        const row = {
          fileId: file.id,
          fileName: file.name,
          fileSize: fileSize,
          validateMd5: '0%',
          progress: '等待上传',
          percentage: 0,
          speed: '0KB/s',
          state: '就绪'
        };
        that.fileList.push(row)
        that.uploadToServer()
      })

      this.uploader.on('uploadProgress', (file, percentage) => {
        // 找到对应文件并更新进度和速度
        let targetFile = this.fileList.find(item => item.fileId === file.id)
        if (targetFile) {
          // 计算上传速度
          const currentTime = new Date().getTime()
          const elapsedTime = (currentTime - (targetFile.startTime || currentTime)) / 1000 // 秒
          const uploadedSize = percentage * file.size
          const speed = this.formatFileSize(uploadedSize / elapsedTime) + '/s'
          // 更新文件信息
          targetFile.percentage = parseFloat((percentage * 100).toFixed(2))
          targetFile.speed = speed
          targetFile.startTime = targetFile.startTime || currentTime
        }
      })

      this.uploader.on('uploadSuccess', (file, response) => {
        this.uploadedFiles = []
        if (response.code === 10000) {
          response.data.fileName = response.data.originalName
          response.data.percentage = this.fileList[0].percentage
          response.data.fileSize = this.fileList[0].fileSize
          response.data.speed = this.fileList[0].speed
          this.uploadedFiles.push(response.data)
          // this.$message.success('上传完成')
        } else {
          this.$message.error('上传失败: ' + response.message)
        }
      })

      /**上传之前**/
      uploader.on('uploadBeforeSend', function (block, data, headers) {
        data.fileMd5 = block.file.fileMd5
        data.contentType = block.file.type
        data.chunks = block.file.chunks
        data.zoneTotalMd5 = block.file.fileMd5
        data.zoneMd5 = block.zoneMd5
        data.zoneTotalCount = block.chunks
        data.zoneNowIndex = block.chunk
        data.zoneTotalSize = block.total
        data.zoneStartSize = block.start
        data.zoneEndSize = block.end
        headers.Authorization = that.options.headers.Authorization
      })

      uploader.on('uploadFinished', function () {
        that.uploadStaus = 'el-icon-upload'
        that.$message.success({
          showClose: true,
          message: '文件上传完毕'
        })
      })
    },

    setTableBtn(fileId, showmsg, sid) {
      var fileList = this.fileList
      for (var i = 0; i < fileList.length; i++) {
        if (fileList[i].fileId == fileId) {
          this.fileList[i].progress = showmsg
          this.fileList[i].sid = sid || ''
        }
      }
    },
    removeRow(index, row) {
      this.fileList.splice(index, 1)
      this.removeFileFromUploaderQueue(row.fileId)
      this.$emit('removeRow', index, row)
    },

    removeFileFromUploaderQueue(fileId) {
      const files = this.uploader.getFiles()
      for (let i = 0; i < files.length; i++) {
        if (files[i].id === fileId) {
          this.uploader.removeFile(files[i], true)
          break
        }
      }
    },

    uploadToServer() {
      this.uploadStatus = 'el-icon-loading'
      this.uploadStartTime = new Date()
      this.uploader.upload()
    },

    clearFiles() {
      const that = this
      that.uploadStaus = 'el-icon-upload'
      that.uploader.reset()
      this.$emit('clearFiles', [])
    },
    buildFileType(fileType) {
      var ts = fileType.split(',')
      var ty = ''

      for (var i = 0; i < ts.length; i++) {
        ty = ty + '.' + ts[i] + ','
      }
      return ty.substring(0, ty.length - 1)
    },
    strIsNull(str) {
      if (typeof str == 'undefined' || str == null || str == '') {
        return true
      } else {
        return false
      }
    },
    formatFileSize(size) {
      var fileSize = 0
      if (size / 1024 > 1024) {
        var len = size / 1024 / 1024
        fileSize = len.toFixed(2) + 'MB'
      } else if (size / 1024 / 1024 > 1024) {
        len = size / 1024 / 1024
        fileSize = len.toFixed(2) + 'GB'
      } else {
        len = size / 1024
        fileSize = len.toFixed(2) + 'KB'
      }
      return fileSize
    }
  }
}
</script>
<style>
.center-container {
  transform: scale(1.1); /* 缩放整个容器 */
  margin-left: 300px;
  justify-content: center;
  align-items: center;
  height: 100vh; /* 让容器占满整个视口高度 */
}

.container {
  padding: 30px;
  border: 1px solid #312828;
  border-radius: 5px;
}

.handle-box {
  margin-bottom: 20px;
}

#picker div:nth-child(2) {
  width: 100% !important;
  height: 100% !important;
}


.webuploader-element-invisible {
  position: absolute !important;
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
}

.webuploader-pick-hover {
  background: #409eff;
}

/* 统一设置 label 的字体大小 */
.el-table-column label {
  font-size: 30px;
}

.showMsg {
  margin: 5px;
  font-size: 16px;
}
</style>
